//////////////////////////////////////////////////////////////////
// (c) Copyright 2008- by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//   National Center for Supercomputing Applications &
//   Materials Computation Center
//   University of Illinois, Urbana-Champaign
//   Urbana, IL 61801
//   e-mail: jnkim@ncsa.uiuc.edu
//
// Supported by 
//   National Center for Supercomputing Applications, UIUC
//   Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
/** @file collectives.h
 * @brief mpi collective functions
 *
 * They are intended to be replaced by boost::mpi and hacks for testing only.
 */
#ifndef QMCPLUSPLUS_MPI_COLLECTIVES_H
#define QMCPLUSPLUS_MPI_COLLECTIVES_H
#include <mpi/communicator.h>

#if defined(USE_BOOST_MPI)
namespace  boost { 
#else
#include <mpi/datatype.h>
#endif
  namespace mpi {
  template<typename T>
  inline void
  reduce(communicator& comm, T& in_value, T& out_value)
  {
  }

  template<typename T> 
  inline void
  reduce(communicator& comm, T& inout)
  {
    T saved(inout);
    reduce(comm,saved,inout);
  }

  template<typename T>
  inline void
  allreduce(communicator& comm, T& in_value, T& out_value)
  {
  }

  template<typename T> 
  inline void
  allreduce(communicator& comm, T& inout)
  {
    T saved(inout);
    reduce(comm,saved,inout);
  }

  template<typename T> 
  inline void
  alltoall(communicator& comm, T* in, T* out, int n)
  {
  }

#if defined(HAVE_MPI)
//macros when boost::mpi cannot be used
#define BOOSTSUP_MPI_REDUCE(CppType, Op)                          \
template <>                                                       \
inline void                                                       \
reduce(communicator& comm, CppType& in_value, CppType& out_value) \
{                                                                 \
  MPI_Datatype dtype=get_mpi_datatype<CppType>(in_value);         \
  MPI_Reduce(&in_value, &out_value, 1, dtype, Op, 0, comm);       \
}                                                                 \
template <>                                                       \
inline void                                                       \
allreduce(communicator& comm, CppType& in_value, CppType& out_value) \
{                                                                 \
  MPI_Datatype dtype=get_mpi_datatype<CppType>(in_value);         \
  MPI_Allreduce(&in_value, &out_value, 1, dtype, Op, comm);       \
}                                                                 \
template <>                                                       \
inline void                                                       \
alltoall(communicator& comm, CppType* in_ptr, CppType* out_ptr, int n) \
{                                                                 \
  MPI_Datatype dtype=get_mpi_datatype<CppType>(*in_ptr);          \
  MPI_Alltoall(in_ptr, n, dtype, out_ptr, n, dtype, comm);        \
}

BOOSTSUP_MPI_REDUCE(int,MPI_SUM);

BOOSTSUP_MPI_REDUCE(double,MPI_SUM);

inline void
alltoallv(communicator& comm, double* in_ptr, int *scounts,int *sdispls, double* out_ptr,  int *rcounts, int *rdispls) 
{
  MPI_Alltoallv(in_ptr, scounts, sdispls, MPI_DOUBLE, out_ptr, rcounts, rdispls, MPI_DOUBLE, comm);
}

//template <>     
//inline void     
//alltoall(communicator& comm, double* in_ptr, double* out_ptr, int n) 
//{                                                                 
//  MPI_Alltoall(in_ptr, n, MPI_DOUBLE, out_ptr, n, MPI_DOUBLE, comm);       
//}


#define BOOSTSUB_REDUCE_SERIALIZED(CppType,ContType,Op)            \
  template<>                                                       \
  inline void reduce(communicator& comm,                           \
      ContType& in_value, ContType& out_value)                     \
  {                                                                \
    MPI_Datatype dtype=get_mpi_datatype<CppType>(in_value[0]);     \
    MPI_Reduce(&in_value[0], &out_value[0], in_value.size(), dtype \
        , Op, 0, comm);                                            \
  }                                                                \

BOOSTSUB_REDUCE_SERIALIZED(double,std::vector<double>,MPI_SUM);

BOOSTSUB_REDUCE_SERIALIZED(int,std::vector<int>,MPI_SUM);

#endif
}//mpi-namespace
#if defined(USE_BOOST_MPI)
}//boost-namespace
#endif

#endif //  QMCPLUSPLUS_MPI_COLLECTIVES_H
/***************************************************************************
 * $RCSfile$   $Author: jnkim $
 * $Revision: 2809 $   $Date: 2008-07-14 10:52:34 -0500 (Mon, 14 Jul 2008) $
 * $Id: collectives.h 2809 2008-07-14 15:52:34Z jnkim $ 
 ***************************************************************************/
